/*
*
==============================================================================
*  Name        : 
*  Part of     : Omen Game Engine
*  Description : 
*  Version     : 1.0
*
*  Copyright (c) 2013 Lauri Kortevaara.
* 
==============================================================================
*/

#ifndef OMEN_KERNEL_H
#define OMEN_KERNEL_H

/// Omen Headers
#include "IOmenKernel.h"

#include "OmenConfig.h"
#include "OmenPlugin.h"

#include "OmenGraphicsServer.h"
#include "OmenInputServer.h"
#include "OmenStorageServer.h"

#include "OmenProperty.h"
#include "OmenEvents.h"

/// Omen Interface headers
#include <OmenXmlReader.h>

/// STL Headers
#include <string>
#include <map>
#include <memory>

#ifndef WinMessageHandler
    typedef int (__stdcall* WinMessageHandler)(HWND,UINT,WPARAM,LPARAM);
#endif

namespace Omen {

  /// <summary>The engine's core</summary>
  class Kernel : public Omen::IKernel, public Omen::PropertyObject 
  {
        static std::unique_ptr<Omen::Kernel> _instance; // This is the instance ptr of Kernel
        Kernel();                          // Private constructor

        /// Kernel factory function
  public:
        static IKernel& getKernel();

  public :
      //typedef int (__stdcall *Omen::EventHandler)(Omen::Event& event);

  private:
      typedef std::map<std::wstring, Plugin> PluginMap;  /// <summary>Map of plugins by their associated file names</summary>

  public: 
        /// Omen::IKernel interface functions
        virtual Omen::IGraphicsServer*    getGraphicsServer(); /// <summary>Accesses the graphics server</summary>        
        virtual Omen::IStorageServer*     getStorageServer();  /// <summary>Accesses the storage server</summary>
        virtual Omen::IInputServer*       getInputServer();    /// <summary>Access the input server</summary>
        virtual Omen::ISceneManager*      getSceneManager();    /// <summary>Access the scene manager</summary>
        virtual Omen::IAssetManager*      getAssetManager();   /// <summary>Access the asset manager</summary>
        
        virtual void loadPlugin(const std::wstring &filename);      /// <summary>Loads a plugin</summary>
        virtual void loadPlugins(const std::wstring &pluginPath);   /// <summary>Loads all plugins in a directory</summary>

        virtual bool initialize( const std::wstring& configFilePath = OMEN_DEFAULT_CONFIG_FILE);    /// <summary>Initialize the Engine using given config file. By default it's config.cfg</summary>
        virtual void run();
        virtual void shutDown();

        // Event handling
        virtual void sendEvent( const Omen::Event* event );
        virtual void registerEventHandler( Omen::IEventHandler* handler );
        
        virtual WinMessageHandler GetWinProc();

        /// property functions for each of the types
        virtual Omen::Property& getProperty( std::wstring strPropertyName );
        virtual void  setProperty( std::wstring strPropertyName, const std::wstring& property);


        /// property objects, containing several <std:wstring, std::wstring> key,value properties
        virtual bool addPropertyObject( Omen::PropertyObject& propertyObject );
        virtual bool getPropertyObject( const std::wstring& strPropertyObjectName, Omen::PropertyObject& propertyObject );

        /// Timer interface
        virtual Omen::ITimer* timer();      /// <summary>Returns the kernel timer</summary>

        static int (__stdcall MessageHandler)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lparam);

protected:
        void parseConfigNode( Omen::XmlNode& node );

private:
        bool frame();

private: 
        PluginMap           m_loadedPlugins;      /// <summary>All plugins currently loaded</summary>
        
        IStorageServer*     m_storageServer;      /// <summary>Manages storage-related tasks for the engine</summary>
        IGraphicsServer*    m_graphicsServer;     /// <summary>Manages graphics-related tasks for the engine</summary>
        IInputServer*       m_inputServer;
        ISceneManager*      m_sceneManager;
        IAssetManager*      m_assetManager;

        Omen::ITimer*       m_pTimer;               /// <summary>The kernel timer</summary>

        std::map< std::wstring, Omen::Property > m_properties;

        std::vector< Omen::IEventHandler* > m_eventHandlers;
        std::vector< Omen::PropertyObject > m_propertyObjects;
  };



/////////////
// GLOBALS //
/////////////

} // namespace Omen

#endif // OMEN_KERNEL_H